package cn.xumaoyang.user.service.impl;
import cn.xumaoyang.basic.exception.BusinessException;
import cn.xumaoyang.basic.service.impl.BaseServiceImpl;
import cn.xumaoyang.basic.util.MD5Utils;
import cn.xumaoyang.basic.util.StrUtils;
import cn.xumaoyang.basic.util.UserConstants;
import cn.xumaoyang.user.domain.Logininfo;
import cn.xumaoyang.user.domain.User;
import cn.xumaoyang.user.dto.Userdto;
import cn.xumaoyang.user.mapper.LogininfoMapper;
import cn.xumaoyang.user.mapper.UserMapper;
import cn.xumaoyang.user.service.IUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    //保存数据。
    @Autowired
    private UserMapper userMapper;

    //验证码
    @Autowired
    private RedisTemplate redisTemplate;

    //保存数据。
    @Autowired
    private LogininfoMapper logininfoMapper;


    @Override
    public void loadByPhone(Userdto userdto) {
        //第一步。判断获取到的值是否为空,StringUtils.isEmpty的意思是为空
        if (StringUtils.isEmpty(userdto.getPhone())
            || StringUtils.isEmpty(userdto.getPassword())
            || StringUtils.isEmpty(userdto.getPasswordRepeat())
            || StringUtils.isEmpty(userdto.getVerifyCode())){
            throw new BusinessException("请输入必须填写的信息");
        }
        //第二步，判断手机号码是否已经注册.
        //把前端传递来的手机号码单独传入数据库比较手机号码是否在数据库中已经存在。
        User u = userMapper.loadByPhone(userdto.getPhone());
        if (u != null){
            throw new BusinessException("该用户已经存在请直接登录");
        }

        //第三步，判断两次输入的密码是否一致,这里写入不一致，
        if (!userdto.getPassword().equals(userdto.getPasswordRepeat())){
            throw new BusinessException("两次输入的密码不一致请重新输入");
        }
        //第四步，判断验证码是否过期。
        //首先根据传递过来的手机号码来获取到验证码,也可以理解为Redis有效存储期为三分钟，如果获取出来的数据为null，那就是不存在了。
        Object o = redisTemplate.opsForValue().get(UserConstants.BUSINESS_TYPE_REGISTER + userdto.getPhone());
        if (o == null){
            throw new BusinessException("验证码已经过期，请重新获取");
        }
        //第五步，如果验证码对了，那就判断我们发给用户的验证码和用户输入的验证码是否一致。
        //首先我们先获取到验证码，因为验证码加入了时间戳，我们需要分割来单独获取验证码。
        String code = o.toString().split(":")[0];
        //判断验证码是否一致，并且不区分大小写,这里写入不一致。
        if (!userdto.getVerifyCode().equalsIgnoreCase(code)){
            //那就报错。
            throw new BusinessException("验证码错误请重新输入或者重新获取验证码");
        }
        //第六步，上方验证全通过，则可以保存数据，需要保存两张表。
        //第一张。t_user表。
        User user = user2logininfo(userdto);
        //第二张表，t_logininfo。
        Logininfo logininfo = logininfo2user(user);
        //数据库保存t_logininfo的数据。
        logininfoMapper.add(logininfo);
        //数据库保存t_user表，这里需要注意t_user表里有logininfo ID这个字段，需要获取再赋值。
        user.setLogininfo_id(logininfo.getId()); //数据现在已经保存再user里，等待进入数据库,一定要设置返回值id，在xml里ukk。
        userMapper.add(user);
    }

    //把前端传来的参数，拷贝给User,注：这种方法必须两个表的字段名一致，并且获取的也一致。
    private User user2logininfo(Userdto userdto) {
        //先获取到实体类。
        User user = new User();
        //获取到盐值属性，也就是把密码复杂化，32代表盐值长度。
        String mm = StrUtils.getComplexRandomString(32);
        //使用工具类密码加密，再加上上方盐值属性，得到新的复杂密码。
        String s = MD5Utils.encrypByMd5(userdto.getPassword() + mm);
        //根据数据库表所需参数来赋值,表里的name.
        user.setUsername(userdto.getPhone());
        //表里phone.
        user.setPhone(userdto.getPhone());
        //表里的盐值赋值。
        user.setSalt(mm);
        //加密后的密码
        user.setPassword(s);
        //返回user。
        return user;
    }

    //把前端传来的参数，拷贝给Logininfo,注：这种方法必须两个表的字段名一致，并且获取的也一致。
    //接收类型为Logininfo，接收对象为user。
    private Logininfo logininfo2user(User user) {
        //获取对象
        Logininfo logininfo = new Logininfo();
        //拷贝,必须两方所需数据一致，user已经获取，Logininfo也只需要这些数据。
        BeanUtils.copyProperties(user,logininfo); //第一个为A，第二个为B，A传B。
        //返回，谁调用我就返回给谁。
        return logininfo;
    }


}
